package meuteste;

/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.TooManyListenersException;
import jd2xx.*;

/**
 *
 * @author Tiago
 */
/**
 * Esta classe tratará dos eventos de envio e de recebimento de dados na porta
 * serial.
 */
public class PortaSerial {

    private JD2XX jd;
    private JD2XXOutputStream outputStream;
    private JD2XXInputStream inputStream;
    private DataHora dataHora;
    boolean controle = false;
    private Conexao conexao;
    private boolean termineiReq = true;
    private int[][] respostaRecebidaSemHorario;
    private int[][] semRespostaRecebida;
    private int[][] vezesResetadas;
    private int[][] vezesHorarioForaDoProtoclo;
    private OrdemDeServiço ordemDeServiço;

    public PortaSerial(int baudrate, DataHora dataHora, Conexao conexao, OrdemDeServiço ordemDeServiço) throws TooManyListenersException, SQLException, IOException, InterruptedException {//, Timer timer, Timer timer2) throws TooManyListenersException {
        jd = new JD2XX();
        Object[] devs = jd.listDevicesByDescription();
        for (int i = 0; i < devs.length; ++i) {
            System.out.println(devs[i]);
        }

        jd.open(0);
        jd.setBaudRate(baudrate);
        jd.setDataCharacteristics(JD2XX.BITS_8, JD2XX.STOP_BITS_1, JD2XX.PARITY_NONE);
        jd.setFlowControl(JD2XX.FLOW_NONE, 0, 0);
        outputStream = new JD2XXOutputStream(jd);
        inputStream = new JD2XXInputStream(jd);

        this.dataHora = dataHora;
        this.conexao = conexao;
        respostaRecebidaSemHorario = new int[15][1];
        semRespostaRecebida = new int[15][1];
        vezesResetadas = new int[15][1];
        vezesHorarioForaDoProtoclo = new int[15][1];
        this.ordemDeServiço = ordemDeServiço;
    }

    public void enviarRequisicaoNo() throws IOException, SQLException, InterruptedException {
        int dia = dataHora.getDia();
        int mes = dataHora.getMes() + 1;
        int ano = dataHora.getAno() - 2000;
        int hora = dataHora.getHora();
        int min = dataHora.getMinuto();
        StringBuilder comando = new StringBuilder(ordemDeServiço.getRequisicaoDeDados(dia, mes, ano, hora, min));
        if (comando.substring(0).equals("minuto = 0")) {
        } else {
            termineiReq = false;
            ResultSet rst;
            rst = conexao.selectFromWhere("select mac, id ", "from gerentes ", "");
            boolean primeiraVez = true;
            while (rst.next()) {
                StringBuilder stbRes = new StringBuilder(1000);
                if (primeiraVez) {
                    primeiraVez = false;
                    if (rst.getInt("mac") < 10) {
                        comando.append("00").append(rst.getInt("mac")).append("t  ");
                    } else if (rst.getInt("mac") < 100) {
                        comando.append("0").append(rst.getInt("mac")).append("t  ");
                    } else {
                        comando.append(rst.getInt("mac")).append("t  ");
                    }
                } else {
                    if (rst.getInt("mac") < 10) {
                        comando.replace(comando.length() - 6, comando.length() - 3, "00" + rst.getInt("mac"));
                    } else if (rst.getInt("mac") < 100) {
                        comando.replace(comando.length() - 6, comando.length() - 3, "0" + rst.getInt("mac"));;
                    } else {
                        comando.replace(comando.length() - 6, comando.length() - 3, rst.getString("mac"));
                    }
                }
                boolean recebiResposta = false;
                while(!recebiResposta) {
                    outputStream.write(comando.substring(0).getBytes());
                    System.out.println("Enviado: " + comando);
                    Thread.sleep(500);
                    boolean controleReqDados = false;
                    boolean recebirespostaReqDados = false;
                    int countRespostaReqDados = 0;
                    boolean primeiroI = true;
                    int count = 0;
                    while (recebirespostaReqDados == false) {
//                        boolean primeiroI = true;
//                        for (int j = 0; j <= jd.getQueueStatus(); j++) {
                        if(jd.getQueueStatus() > 0) {
                            char aux = (char) (inputStream.read());
                            if (aux == 'i') {
                                if (controleReqDados == false) {
                                    controleReqDados = true;
                                    stbRes.append(aux);
                                }
                            } else if (aux != 'i' && aux != 't' && controleReqDados == true) {
                                stbRes.append(aux);
                                countRespostaReqDados++;
                            } else if (aux == 't' && controleReqDados == true) {
                                stbRes.append(aux);
                                controleReqDados = false;
                                recebirespostaReqDados = true;
                            }
                        } else {
                            count++;
                            Thread.sleep(500);
                            if(count > 80) {
                                outputStream.write(comando.substring(0).getBytes());
                                System.out.println("Enviado: " + comando);
                           }
                        }
                    }
                    Thread.sleep(500);
                    System.out.print("Recebido: " + stbRes.substring(0));
                    switch (stbRes.substring(0)) {
                        case "iR?t":
                            System.out.print(" Sem rota para o gerente\n");
                            recebiResposta = true;
                            break;
                        case "iP?t":
                            System.out.print(" Erro no protocolo\n");
                            recebiResposta = true;
                            break;
                        case "iG?t":
                            System.out.print(" Gerente não respondeu\n");
                            semRespostaRecebida[rst.getInt(2) - 1][0] = semRespostaRecebida[rst.getInt(2) - 1][0] + 1;
                            recebiResposta = true;
                            break;
                        case "iT?t":
                            System.out.print(" Coordenador ocupado\n");
                            recebiResposta = true;
                            break;
                        case "iD?t":
                            System.out.print(" Sem dados disponiveis no gerente\n");
                            recebiResposta = true;
                            break;
                        case "iH?t":
                            System.out.print(" Sem hora/Data disponivel\n");
                            respostaRecebidaSemHorario[rst.getInt("id") - 1][0] = respostaRecebidaSemHorario[rst.getInt("id") - 1][0] + 1;
                            recebiResposta = true;
                            break;
                        case "":
                            System.out.println("Não veio resposta");
                            break;
                        default:
                            if (!stbRes.substring(0).matches("iX(.*)") ) {
                                int countEspacosVazios = 0;
                                boolean chegueiFinalString = false;
                                int auxPointer = 0;
                                while (!chegueiFinalString) {
                                    auxPointer = stbRes.indexOf(" ", auxPointer);
                                    if (auxPointer == -1) {
                                        chegueiFinalString = true;
                                    } else {
                                        auxPointer++;
                                        countEspacosVazios++;
                                    }
                                }
                                String where = "where gerente_id = " + rst.getInt(2);
                                ResultSet rst3 = conexao.selectFromWhere("select id, divisao ", "from sensores ", where);
                                int countAlicatesBD = 0;
                                while (rst3.next()) {
                                    countAlicatesBD++;
                                }
                                if (countAlicatesBD == countEspacosVazios + 1) {
                                    System.out.print("\n");
                                    respostaRecebidaSemHorario[rst.getInt("id") - 1][0] = 0;
                                    StringBuilder stbRes2 = new StringBuilder(stbRes.deleteCharAt(0).deleteCharAt(stbRes.length() - 1));
                                    int auxPointer2 = 0;
                                    rst3.afterLast();
                                    while (rst3.previous()) {
                                        conexao.gravarLeituras(rst3.getInt("id"), new Float(Integer.parseInt(stbRes2.substring(auxPointer2, auxPointer2 + 3)) / rst3.getDouble("divisao")), min, hora, dia, mes, ano);
                                        auxPointer2 = auxPointer2 + 4;
                                    }
                                } else {
                                    respostaRecebidaSemHorario[rst.getInt("id") - 1][0] = 0;
                                    System.out.print(" Numero de alicates diferente do numero de alicates no banco de dados\n");
                                }
                                recebiResposta = true;
                            } else {
                                System.out.println("=== Aguardando ===");
                                stbRes.delete(0, stbRes.length());
                                Thread.sleep(5000);
                            }
                            break;
                    }
                    termineiReq = true;
                    if (respostaRecebidaSemHorario[rst.getInt("id") - 1][0] > 2) {
                        ResultSet rstPossuiALicate = conexao.selectFromWhere("SELECT gerente_id ", "FROM sensores ", "where gerente_id = (SELECT id FROM gerentes g where mac = " + rst.getInt("mac") + ")");
                        if (!rstPossuiALicate.next()) {
                            respostaRecebidaSemHorario[rst.getInt("id") - 1][0] = 0;
                        } else {
                            System.out.println("==== Atualizando rtc do gerente " + rst.getInt("mac") + " ====");
                            StringBuilder stbHorario;
                            if (rst.getInt("mac") < 10) {
                                stbHorario = new StringBuilder(reqRTC(new StringBuilder("00" + rst.getInt("mac"))));
                            } else if (rst.getInt("mac") < 100) {
                                stbHorario = new StringBuilder(reqRTC(new StringBuilder("0" + rst.getInt("mac"))));
                            } else {
                                stbHorario = new StringBuilder(reqRTC(new StringBuilder(rst.getInt("mac"))));
                            }
                            if ((stbHorario.substring(0).equals("i?Rt") == false) && (stbHorario.substring(0).equals("i?Pt") == false) && (stbHorario.substring(0).equals("i?Dt") == false) && (stbHorario.substring(0).equals("i?Gt") == false) && (stbHorario.substring(0).equals("i?Ht") == false) && (stbHorario.substring(0).equals("iiiiT?t") == false) && (stbHorario.substring(0).equals("") == false)) {
                                int diaRTC, mesRTC, anoRTC, horaRTC, minRTC;
                                try {
                                    diaRTC = Integer.parseInt(stbHorario.substring(1, 3));
                                    mesRTC = Integer.parseInt(stbHorario.substring(4, 6));
                                    anoRTC = Integer.parseInt(stbHorario.substring(7, 9));
                                    horaRTC = Integer.parseInt(stbHorario.substring(10, 12));
                                    minRTC = Integer.parseInt(stbHorario.substring(13, 15));
                                    if (diaRTC != dataHora.getDia() || mesRTC != (dataHora.getMes() + 1) || anoRTC != (dataHora.getAno() - 2000) || horaRTC != dataHora.getHora() || minRTC != dataHora.getMinuto()) {
                                        if (diaRTC == 01 && mesRTC == 01 && anoRTC == 01) {
                                            vezesResetadas[rst.getInt("mac") - 1][0] = vezesResetadas[rst.getInt("mac") - 1][0] + 1;
                                        }
                                        if (rst.getInt("mac") < 10) {
                                            enviarRTCUnicast(new StringBuilder("00" + rst.getInt("mac")));
                                        } else if (rst.getInt("mac") < 100) {
                                            enviarRTCUnicast(new StringBuilder("0" + rst.getInt("mac")));
                                        } else {
                                            enviarRTCUnicast(new StringBuilder(rst.getInt("mac")));
                                        }
                                    }
                                } catch (NumberFormatException ex) {
                                    System.out.println("==== Horario recebido com erro do gerente " + rst.getInt("mac") + "====");
                                    System.out.println("Recebido: " + stbHorario);
                                    vezesHorarioForaDoProtoclo[rst.getInt("id") - 1][0] = vezesHorarioForaDoProtoclo[rst.getInt("id") - 1][0] + 1;
                                }
                                respostaRecebidaSemHorario[rst.getInt("id") - 1][0] = 0;
                            }
                        }
                    }
                }
            }
        }
    }

    public String requisitarRotas(StringBuilder text) throws IOException, InterruptedException {
        StringBuilder stbRes = new StringBuilder(1000);
        char[] gerente;
        gerente = new char[text.length()];
        for (int i = 0; i < text.length(); i++) {
            gerente[i] = text.charAt(i);
        }
        String comando = ordemDeServiço.getExibirRotas(Integer.parseInt(new String(gerente)));
        outputStream.write(comando.getBytes());
        System.out.println("Enviado: " + comando);
        Thread.sleep(500);
        boolean recebiRotas = false;
        boolean controleRotas = false;
        int countExibirRotas = 0;
        boolean primeiroI = true;
        while (recebiRotas == false) {
            char aux;
//            boolean primeiroI = true;
//            for (int j = 0; j <= jd.getQueueStatus(); j++) {
            if(jd.getQueueStatus() > 0) {
                aux = (char) (inputStream.read());
                if (aux == 'i') {
                    if (primeiroI) {
                        primeiroI = !primeiroI;
                    } else {
//                        System.out.print("i");
                    }
                    if (controleRotas == false) {
                        controleRotas = true;
                        stbRes.append(aux);
                    }
                } else if (aux != 'i' && aux != 't' && controleRotas == true) {
                    stbRes.append(aux);
                    countExibirRotas++;
                } else if (aux == 't' && controleRotas == true) {
                    stbRes.append(aux);
                    controleRotas = false;
                    recebiRotas = true;
                }
            }
        }
        Thread.sleep(500);
        System.out.println("Recebido: " + stbRes);
        return stbRes.substring(0);
    }

    public String pingar(StringBuilder text) throws IOException, InterruptedException {
        int countRespostaPing = 0;
        StringBuilder stbRes = new StringBuilder(1000);
        char[] gerente;
        gerente = new char[text.length()];
        for (int i = 0; i < text.length(); i++) {
            gerente[i] = text.charAt(i);
        }
        String comando = ordemDeServiço.getIndiceOuNDeFalhas(Integer.parseInt(new String(gerente)));
        outputStream.write(comando.getBytes());
        System.out.println("Enviado: " + comando);
        Thread.sleep(500);
        boolean recebiPing = false;
        boolean controlePing = false;
        boolean primeiroI = true;
        while (recebiPing == false) {
            char aux;
//            boolean primeiroI = true;
//            for (int j = 0; j <= jd.getQueueStatus(); j++) {
            if(jd.getQueueStatus() > 0) {
                aux = (char) (inputStream.read());
                if (aux == 'i') {
                    if (primeiroI) {
                        primeiroI = !primeiroI;
                    } else {
//                        System.out.print("i");
                    }
                    if (controlePing == false) {
                        controlePing = true;
                        stbRes.append(aux);
                    }
                } else if (aux != 'i' && aux != 't' && controlePing == true) {
                    stbRes.append(aux);
                    countRespostaPing++;
                } else if (aux == 't' && controlePing == true) {
                    stbRes.append(aux);
                    controlePing = false;
                    recebiPing = true;
                }
            }
        }
        Thread.sleep(500);
        System.out.println("Recebido: " + stbRes);
        return stbRes.substring(0);
    }

    public void enviarRTCBroadcast() throws IOException, InterruptedException {
        String comando = ordemDeServiço.getAjusteDeTodosOsRelogios();
        outputStream.write(comando.getBytes());
        System.out.println("Enviado: " + comando);
        Thread.sleep(500);
    }

    public String enviarRTCUnicast(StringBuilder text) throws IOException, InterruptedException {
        int countRespostaRTC = 0;
        char[] gerente;
        gerente = new char[text.length()];
        for (int i = 0; i < text.length(); i++) {
            gerente[i] = text.charAt(i);
        }
        String comando = ordemDeServiço.getAjusteDeUmrelogio(Integer.parseInt(new String(gerente)));
        outputStream.write(comando.getBytes());
        Thread.sleep(500);
        System.out.println("Enviado: " + comando);
        boolean recebiRTC = false;
        boolean controleRTC = false;
        boolean primeiroI = true;
        StringBuilder stbRes = new StringBuilder(1000);
        while (recebiRTC == false) {
            char aux;
//            boolean primeiroI = true;
//            for (int j = 0; j <= jd.getQueueStatus(); j++) {
            if(jd.getQueueStatus() > 0) {
                aux = (char) (inputStream.read());
                if (aux == 'i') {
                    if (primeiroI) {
                        primeiroI = !primeiroI;
                    } else {
                        System.out.print("i");
                    }
                    if (controleRTC == false) {
                        controleRTC = true;
                        stbRes.append(aux);
                    }
                } else if (aux != 'i' && aux != 't' && controleRTC == true) {
                    stbRes.append(aux);
                    countRespostaRTC++;
                } else if (aux == 't' && controleRTC == true) {
                    stbRes.append(aux);
                    countRespostaRTC = 0;
                    controleRTC = false;
                    recebiRTC = true;
                }
            }
        }
        Thread.sleep(500);
        System.out.println("Recebido: " + stbRes);
        return stbRes.substring(0);
    }

    public String reqRTC(StringBuilder text) throws IOException, InterruptedException {
        int countRespostaRTC = 0;
        char[] gerente;
        gerente = new char[text.length()];
        for (int i = 0; i < text.length(); i++) {
            gerente[i] = text.charAt(i);
        }
        String comando = ordemDeServiço.getConfirmacaoDataHora(Integer.parseInt(new String(gerente)));
        outputStream.write(comando.getBytes());
        System.out.println("Enviado: " + comando);
        Thread.sleep(500);
        boolean recebiRTC = false;
        boolean controleRTC = false;
        boolean primeiroI = true;
        StringBuilder stbRes = new StringBuilder(1000);
        while (recebiRTC == false) {
            char aux;
//            boolean primeiroI = true;
//            for (int j = 0; j <= jd.getQueueStatus(); j++) {
            if(jd.getQueueStatus() > 0) {
                aux = (char) (inputStream.read());
                if (aux == 'i') {
                    if (primeiroI) {
                        primeiroI = !primeiroI;
                    } else {
//                        System.out.print("i");
                    }
                    if (controleRTC == false) {
                        controleRTC = true;
                        stbRes.append(aux);
                    }
                } else if (aux != 'i' && aux != 't' && controleRTC == true) {
                    stbRes.append(aux);
                    countRespostaRTC++;
                } else if (aux == 't' && controleRTC == true) {
                    stbRes.append(aux);
                    controleRTC = false;
                    recebiRTC = true;
                }
            }
        }
        Thread.sleep(500);
        System.out.println("Recebido: " + stbRes);
        return stbRes.substring(0);
    }

    public String gerarRotas() throws IOException, InterruptedException {
        StringBuilder stbRes = new StringBuilder(1000);
        String comando = ordemDeServiço.getGerarRotas();
        outputStream.write(comando.getBytes());
        System.out.println("Enviado: " + comando);
        Thread.sleep(500);
        return stbRes.substring(0);
    }

    public boolean getTerminouReq() {
        return termineiReq;
    }
}
